package com.horizon.manage.student.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.horizon.common.constrants.HorizonResultCodeEnum;
import com.horizon.common.exception.HorizonException;
import com.horizon.manage.student.constants.StudentDictKeyEnum;
import com.horizon.manage.student.constants.StudentConstants;
import com.horizon.manage.student.dto.StudentDto;
import com.horizon.manage.student.entity.Student;
import com.horizon.manage.student.mapper.StudentMapper;
import com.horizon.manage.student.service.IStudentService;
import com.horizon.modules.system.entity.User;
import com.horizon.modules.system.service.IDictService;
import com.horizon.modules.system.service.IPostService;
import com.horizon.modules.system.service.IUserService;
import lombok.AllArgsConstructor;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Objects;
import java.util.Optional;

/**
 * 学生扩展信息服务实现.
 *
 * @author zhaoshb
 * @since 2022/11/28 23:51
 */
@Service
@AllArgsConstructor
public class StudentServiceImpl extends BaseServiceImpl<StudentMapper, Student> implements IStudentService {

    private IDictService dictService;

    private IUserService userService;

    private IPostService postService;

    @Override
    @Transactional
    public Optional<Long> create(StudentDto studentDto) {
        Optional<User> optUser = findOrCreateUser(studentDto);
        if (!optUser.isPresent()) {
            return Optional.empty();
        }
        Optional<Student> optStudentExtendInfoEntity = findOrCreateStudent(optUser.get(), studentDto);
        return optStudentExtendInfoEntity.map(Student::getId);
    }

    @Transactional
    public boolean update(StudentDto studentDto) throws HorizonException {
        Student extendInfoEntity = baseMapper.selectById(studentDto.getId());
        if (Objects.isNull(extendInfoEntity)) {
            throw new HorizonException(HorizonResultCodeEnum.STUDENT_EXTEND_INFO_NOT_EXIST);
        }
        User user = userService.getById(extendInfoEntity.getUserId());
        if (Objects.isNull(user)) {
            throw new HorizonException(HorizonResultCodeEnum.USER_INFO_NOT_EXIST);
        }
        merge(extendInfoEntity, studentDto);
        merge(user, studentDto);
        return updateById(extendInfoEntity) && userService.updateById(user);
    }

    @Override
    @Transactional
    public boolean delete(Long studentExtendInfoId) {
        Student extendInfoEntity = baseMapper.selectOne(Wrappers.<Student>query().lambda().eq(Student::getId, studentExtendInfoId));
        if (Objects.isNull(extendInfoEntity)) {
            return true;
        }
        baseMapper.deleteById(studentExtendInfoId);
        userService.getBaseMapper().deleteById(extendInfoEntity.getUserId());
        return true;
    }

    private void merge(Student extendInfo, StudentDto dto) {
        extendInfo.setPhotoUrl(dto.getPhotoUrl());
        extendInfo.setIdCardNumber(dto.getIdCardNumber());
        extendInfo.setNumber(dto.getNumber());
        extendInfo.setStatusNumber(dto.getStatusNumber());
    }

    private void merge(User user, StudentDto dto) {
        user.setSex(dto.getSex());
        user.setAvatar(dto.getPhotoUrl());
        user.setBirthday(dto.getBirthday());
        user.setStatus(dto.getStatus());
        user.setDeptId(dto.getClassId());
    }

    private Optional<User> findOrCreateUser(StudentDto studentDto) {
        User user = new User();
        user.setAccount(studentDto.getNumber());
        User dbUser = userService.getBaseMapper().selectOne(Wrappers.<User>query().lambda().eq(User::getTenantId, user.getTenantId()).eq(User::getAccount, user.getAccount()));
        if (Objects.nonNull(dbUser)) {
            return Optional.of(dbUser);
        }
        user.setTenantId(studentDto.getTenantId());
        user.setPassword(getStudentInitPassword());
        user.setName(studentDto.getName());
        user.setSex(studentDto.getSex());
        user.setAvatar(studentDto.getPhotoUrl());
        user.setDeptId(studentDto.getClassId());
        user.setPostId(getStudentPostId(studentDto.getTenantId()));
        return userService.save(user) ? Optional.of(user) : Optional.empty();
    }

    private Optional<Student> findOrCreateStudent(User user, StudentDto studentDto) {
        Student extendInfoEntity = new Student();
        extendInfoEntity.setUserId(user.getId());
        Student dbStudent = baseMapper.selectOne(Wrappers.<Student>query().lambda().eq(Student::getUserId, user.getId()));
        if (Objects.nonNull(dbStudent)) {
            return Optional.of(dbStudent);
        }
        extendInfoEntity.setNumber(studentDto.getNumber());
        extendInfoEntity.setIdCardNumber(studentDto.getIdCardNumber());
        extendInfoEntity.setPhotoUrl(studentDto.getPhotoUrl());
        extendInfoEntity.setStatusNumber(studentDto.getStatusNumber());
        return save(extendInfoEntity) ? Optional.of(extendInfoEntity) : Optional.empty();
    }

    private String getStudentInitPassword() {
        return dictService.getValue(StudentDictKeyEnum.INITIALIZE_PASSWORD.getCode(), StudentDictKeyEnum.INITIALIZE_PASSWORD.getKey());
    }

    private String getStudentPostId(String tenantId) {
        return postService.getPostIds(tenantId, StudentConstants.STUDENT_POST_CODE);
    }

}



